package com.kummuna.util.maps;

import com.kummuna.ui.AddWaterLeak;
import com.kummuna.util.json.DirectionsJSONParser;
import com.kummuna.R;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONObject;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

import android.R.layout;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class mapDistance extends Activity implements LocationListener {
	GoogleMap map;
	MapView mapView;
	ArrayList<LatLng> markerPoints;
	TextView tvDistance;
	String result;
	float[] distance = new float[1];
	private Location locationPresent;
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map_distance);

		tvDistance = (TextView) findViewById(R.id.tv_Distance);
		markerPoints = new ArrayList<LatLng>();

		setUpMapIfNeeded();
		setUpLocation();
		map.setInfoWindowAdapter(new InfoWindowAdapter() {

			@Override
			public View getInfoWindow(Marker arg0) {
				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public View getInfoContents(Marker arg0) {
				// Getting view from the layout file info_window_layout
				View v = getLayoutInflater()
						.inflate(R.layout.info_window, null);

				// Getting the position from the marker
				LatLng latLng = arg0.getPosition();

				TextView tv_Topic = (TextView) v.findViewById(R.id.tv_topic);
				TextView tv_Date = (TextView) v.findViewById(R.id.tv_date);
				TextView tv_Detail = (TextView) v.findViewById(R.id.tv_detail);
				TextView tv_Status = (TextView) v.findViewById(R.id.tv_status);

				// Getting reference to the TextView to set topic
				tv_Topic.setText("" + latLng.latitude);
				// Getting reference to the TextView to set date
				tv_Date.setText("" + latLng.longitude);
				// Getting reference to the TextView to set detail
				tv_Detail.setText("" + latLng.latitude);
				// Getting reference to the TextView to set status
				tv_Status.setText("" + latLng.longitude);

				// Returning the view containing InfoWindow contents
				return v;

			}
		});
		map.setOnMapClickListener(new OnMapClickListener() {

			@Override
			public void onMapClick(LatLng latLng) {
				// TODO Auto-generated method stub
				if (markerPoints.size() > 1) {
					markerPoints.clear();
					result = "";
					map.clear();
					tvDistance.setText(result);
				}

				
				markerPoints.add(latLng);

				MarkerOptions markerOptions = new MarkerOptions();
				markerOptions.position(latLng);
				markerOptions.title(latLng.latitude + " : " + latLng.longitude);
				result = "Start \nLatitude = " + latLng.latitude
						+ " Longitude = " + latLng.longitude;

				if (markerPoints.size() == 1) {
					markerOptions.icon(BitmapDescriptorFactory
							.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
					result = "Start \nLatitude = " + latLng.latitude
							+ " Longitude = " + latLng.longitude + "\n";
					tvDistance.setText(result);
				} 
//				else if (markerPoints.size() == 2) {
//					markerOptions.icon(BitmapDescriptorFactory
//							.defaultMarker(BitmapDescriptorFactory.HUE_RED));
//					result += "\nEnd \nLatitude = " + latLng.latitude
//							+ " Longitude = " + latLng.longitude
//							+ "\nDistance = ";
//				}
				
				CameraPosition cameraPosition = new CameraPosition.Builder()
				.target(latLng).zoom(13).bearing(-30).tilt(90).build();
				
				// map.animateCamera(CameraUpdateFactory.newLatLng(latLng));
				map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
				
				// Adding marker on the GoogleMap
				Marker marker = map.addMarker(markerOptions);

				// Showing InfoWindow on the GoogleMap
				marker.showInfoWindow();

				if (markerPoints.size() >= 1) {
				//	LatLng origin = markerPoints.get(0);
					LatLng dest = markerPoints.get(0);
					
					LatLng latLngPresent = new LatLng(locationPresent.getLatitude(), locationPresent.getLongitude());
					
					// Getting URL to the Google Directions API
					String url = getDirectionsUrl(latLngPresent, dest);

					DownloadTask downloadTask = new DownloadTask();

					// Start downloading json data from Google Directions
					// API
					downloadTask.execute(url);

				}

			}
		});
	}

	private void setUpMapIfNeeded() {
		if (map == null) {
			map = ((MapFragment) getFragmentManager()
					.findFragmentById(R.id.map)).getMap();
			map.setMyLocationEnabled(true);
			map.getUiSettings().setCompassEnabled(true);
			map.setTrafficEnabled(true);
			if (map != null) {
				// setUpMap();
			}
		}
	}

	private void setUpMap() {
		LatLng nida = new LatLng(13.769, 100.65);
		map.moveCamera(CameraUpdateFactory.newLatLngZoom(nida, 13));
		map.setMyLocationEnabled(true);
	}

	private void setUpLocation() {

		// Getting Google Play availability status
		int status = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(getBaseContext());

		// Showing status
		if (status != ConnectionResult.SUCCESS) { // Google Play Services are
													// not available

			int requestCode = 10;
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this,
					requestCode);
			dialog.show();

		} else { // Google Play Services are available

			// Getting LocationManager object from System Service
			// LOCATION_SERVICE
			LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

			// Creating a criteria object to retrieve provider
			Criteria criteria = new Criteria();

			// Getting the name of the best provider
			String provider = locationManager.getBestProvider(criteria, true);

			// Getting Current Location
			Location location = locationManager.getLastKnownLocation(provider);

			if (location != null) {
				onLocationChanged(location);
				// set location  Present
				locationPresent = location;
			}

			locationManager.requestLocationUpdates(provider, 2000, 1, this);
		}
	}

	private String getDirectionsUrl(LatLng origin, LatLng dest) {
		// Origin of route
		String str_origin = "origin=" + origin.latitude + ","
				+ origin.longitude;

		// Destination of route
		String str_dest = "destination=" + dest.latitude + "," + dest.longitude;

		// Sensor enabled
		String sensor = "sensor=false";

		// Building the parameters to the web service
		String parameters = str_origin + "&" + str_dest + "&" + sensor;

		// Output format
		String output = "json";

		// Building the url to the web service
		String url = "https://maps.googleapis.com/maps/api/directions/"
				+ output + "?" + parameters;

		return url;
	}

	/** A method to download json data from url */
	private String downloadUrl(String strUrl) throws IOException {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try {
			URL url = new URL(strUrl);

			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();

			// Connecting to url
			urlConnection.connect();

			// Reading data from url
			iStream = urlConnection.getInputStream();

			BufferedReader br = new BufferedReader(new InputStreamReader(
					iStream));

			StringBuffer sb = new StringBuffer();

			String line = "";
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			data = sb.toString();

			br.close();

		} catch (Exception e) {
			Log.d("Exception while downloading url", e.toString());
		} finally {
			iStream.close();
			urlConnection.disconnect();
		}
		return data;
	}

	/** A class to download data from Google Directions URL */
	private class DownloadTask extends AsyncTask<String, Void, String> {

		// Downloading data in non-ui thread
		@Override
		protected String doInBackground(String... url) {

			// For storing data from web service
			String data = "";

			try {
				// Fetching the data from web service
				data = downloadUrl(url[0]);
			} catch (Exception e) {
				Log.d("Background Task", e.toString());
			}
			return data;
		}

		// Executes in UI thread, after the execution of
		// doInBackground()
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);

			ParserTask parserTask = new ParserTask();

			// Invokes the thread for parsing the JSON data
			parserTask.execute(result);
		}
	}

	/** A class to parse the Google Directions in JSON format */
	private class ParserTask extends
			AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

		// Parsing the data in non-ui thread
		@Override
		protected List<List<HashMap<String, String>>> doInBackground(
				String... jsonData) {

			JSONObject jObject;
			List<List<HashMap<String, String>>> routes = null;

			try {
				jObject = new JSONObject(jsonData[0]);
				DirectionsJSONParser parser = new DirectionsJSONParser();

				// Starts parsing data
				routes = parser.parse(jObject);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return routes;
		}

		// Executes in UI thread, after the parsing process
		@Override
		protected void onPostExecute(List<List<HashMap<String, String>>> result) {
			ArrayList<LatLng> points = null;
			PolylineOptions lineOptions = null;
	//		MarkerOptions markerOptions = new MarkerOptions();
			String distance = "";
			String duration = "";

			if (result.size() < 1) {
				Toast.makeText(getBaseContext(), "No Points",
						Toast.LENGTH_SHORT).show();
				return;
			}

			// Traversing through all the routes
			for (int i = 0; i < result.size(); i++) {
				points = new ArrayList<LatLng>();
				lineOptions = new PolylineOptions();

				// Fetching i-th route
				List<HashMap<String, String>> path = result.get(i);

				// Fetching all the points in i-th route
				for (int j = 0; j < path.size(); j++) {
					HashMap<String, String> point = path.get(j);

					if (j == 0) { // Get distance from the list
						distance = (String) point.get("distance");
						continue;
					} else if (j == 1) { // Get duration from the list
						duration = (String) point.get("duration");
						continue;
					}

					double lat = Double.parseDouble(point.get("lat"));
					double lng = Double.parseDouble(point.get("lng"));
					LatLng position = new LatLng(lat, lng);

					points.add(position);
				}

				// Adding all the points in the route to LineOptions
				lineOptions.addAll(points);
				lineOptions.width(2);
				lineOptions.color(Color.RED);
			}

			// Drawing polyline in the Google Map for the i-th route
			map.addPolyline(lineOptions);
			tvDistance.setText("Distance:" + distance + ", Duration:"
					+ duration);
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id._clear:
			map.clear();
			tvDistance.setText("");
			markerPoints.clear();
			break;
		case R.id._normal:
			map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
			break;
		case R.id._satellite:
			map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
			break;
		case R.id._hybrid:
			map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onLocationChanged(Location location) {
		TextView tvLocation = (TextView) findViewById(R.id.tv_location);

		// Getting latitude
		double latitude = location.getLatitude();

		// Getting longitude
		double longitude = location.getLongitude();

		// Creating a LatLng object for the current location
		LatLng latLng = new LatLng(latitude, longitude);

		// Showing the current location in Google Map
		map.moveCamera(CameraUpdateFactory.newLatLng(latLng));

		// Zoom in the Google Map
		map.animateCamera(CameraUpdateFactory.zoomTo(15));

		// Setting latitude and longitude in the TextView tv_location
		tvLocation.setText("Latitude:" + latitude + ", Longitude:" + longitude);

	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub

	}
	

	public void nextpage(View view)
	{
		Intent mapIntent = new Intent(getApplicationContext(),AddWaterLeak.class);
		startActivity(mapIntent);
	}

}